﻿Public NotInheritable Class NormalizedText

    Private Shared ConversionTable As New SortedList(Of Char, Char)
    Private Shared SpecialKanaConversionTable As New SortedList(Of Char, Char)
    Private Shared DakuonTable As New SortedList(Of Char, Char)
    Private Shared HandakuonTable As New SortedList(Of Char, Char)

    Private Text As String

    Public Sub New(ByVal text As String)
        Me.Text = Normalize(text)
    End Sub

    Shared Sub New()

        Dim srcChars = _
            "０１２３４５６７８９ＡＢＣＤＥＦＧＨＩＪＫＬＭＮＯＰＱＲＳＴＵＶＷＸＹＺａｂｃｄｅｆｇｈｉｊｋｌｍｎｏｐｑｒｓｔｕｖｗｘｙｚ" & _
            "！" & ChrW(8221) & "＃＄％＆’（）＊＋，－．／：＜＝＞？＠［￥］＾＿｀｛｜｝￣" & _
            "abcdefghijklmnopqrstuvwxyz" & _
            "｡｢｣､･ｦｧｨｩｪｫｬｭｮｯｱｲｳｴｵﾅﾆﾇﾈﾉﾏﾐﾑﾒﾓﾔﾕﾖﾗﾘﾙﾚﾛﾜﾝﾞﾟ"

        Dim dstChars = _
            "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" & _
            "!""#$%&'()*+,-./:<=>?@[\]^_`{|}~" & _
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ" & _
            "。「」、・ヲァィゥェォャュョッアイウエオナニヌネノマミムメモヤユヨラリルレロワン゛゜"

        For i = 0 To srcChars.Length - 1
            ConversionTable.Add(srcChars(i), dstChars(i))
        Next


        Dim specialHalfKana = "ｶｷｸｹｺｻｼｽｾｿﾀﾁﾂﾃﾄﾊﾋﾌﾍﾎ"
        Dim specialWideKana = "カキクケコサシスセソタチツテトハヒフヘホ"

        For i = 0 To specialHalfKana.Length - 1
            SpecialKanaConversionTable.Add(specialHalfKana(i), specialWideKana(i))
        Next
        For i = 0 To specialWideKana.Length - 1
            SpecialKanaConversionTable.Add(specialWideKana(i), specialWideKana(i))
        Next


        Dim dakuon = "ガギグゲゴザジズゼゾダヂヅデドバビブベボ"
        Dim handakuon = "パピプペポ"

        For i = 0 To dakuon.Length - 1
            DakuonTable.Add(specialWideKana(i), dakuon(i))
        Next
        For i = 0 To handakuon.Length - 1
            HandakuonTable.Add(specialWideKana(i + 15), handakuon(i))
        Next
    End Sub

    Public Overrides Function ToString() As String
        Return Text
    End Function

    Private Shared Function Normalize(ByVal text As String) As String
        Dim sb = New System.Text.StringBuilder(text.Length)
        Dim isSkip As Boolean
        Dim isWhiteSpace As Boolean

        For i = 0 To text.Length - 1
            If isSkip = True Then
                isSkip = False
                Continue For
            End If

            Dim c = text(i)

            If Char.IsWhiteSpace(c) OrElse Char.IsControl(c) Then
                If Not isWhiteSpace Then
                    sb.Append(" "c)
                End If

                isWhiteSpace = True
                Continue For
            End If
            isWhiteSpace = False


            If ConversionTable.ContainsKey(c) Then
                sb.Append(ConversionTable(c))

            ElseIf SpecialKanaConversionTable.ContainsKey(c) Then

                Dim seion = SpecialKanaConversionTable(c)
                If i = text.Length - 1 Then
                    sb.Append(seion)
                    Continue For
                End If

                Dim nextChar = text(i + 1)
                If nextChar = "ﾞ" OrElse nextChar = "゛" Then
                    sb.Append(DakuonTable(seion))
                    isSkip = True

                ElseIf nextChar = "ﾟ" OrElse nextChar = "゜" Then
                    sb.Append(HandakuonTable(seion))
                    isSkip = True

                Else
                    sb.Append(c)
                End If

            Else
                sb.Append(c)

            End If

        Next

        Return sb.ToString
    End Function

End Class